#pragma once

template <class T>
class Buffer2D
{
	private:
		T * m_buffer;
		T * m_lastptr;
		int m_width, m_height;

	public:
		CArray2D() 
		{ 
			m_buffer = 0; 
			m_lastptr = 0;
			m_width = 0;
			m_height = 0;
		}
		~CArray2D() 
		{ 
			Reset();
		}
		void Reset()
		{ 
			if (m_buffer)
			{
				free(m_buffer);
				m_buffer = 0;
				m_lastptr = 0;
				m_width = 0;
				m_height = 0;
			}
		}

		bool Create(int w, int h)
		{
			ASSERT(m_buffer == 0);
			m_buffer = (T *)malloc ( w*h* sizeof(T));
			if (!m_buffer)
				return false;
			m_lastptr = m_buffer;
			m_width = w;
			m_height = h;
			return true;
		}
		__forceinline bool Valid(int x, int y)
		{
			return (((UInt32)x)<(UInt32)m_width && ((UInt32)y)<(UInt32)m_height);
		}
		__forceinline int GetWidth() { return m_width;}
		__forceinline int GetHeight() { return m_height;}
		__forceinline bool IsEmpty() { return m_height * m_width <= 0; }
		__forceinline T Get(int x, int y)
		{
			ASSERT((m_buffer != 0) && (x>=0) && (x<m_width) && (y>=0) && (y<m_height));
			return m_buffer[y*m_width + x];
		}
		__forceinline T *GetPtr(int x, int y)
		{
			ASSERT((m_buffer != 0) && (x>=0) && (x<m_width) && (y>=0) && (y<m_height));
			return &m_buffer[y*m_width + x];
		}
		__forceinline void Set(int x, int y, T v)
		{
			ASSERT((m_buffer != 0) && (x>=0) && (x<m_width) && (y>=0) && (y<m_height));
			m_buffer[y*m_width + x] = v;
		}
		__forceinline void SecureSet(int x, int y, T v)
		{
			if ((x>=0) && (x<m_width) && (y>=0) && (y<m_height))
				m_buffer[y*m_width + x] = v;
		}
		__forceinline void Clear(T v)
		{
			ASSERT(m_buffer != 0);
			//memset((void *)m_buffer, v, sizeof(T) * m_width * m_height);
			for (int i = 0; i< m_width * m_height; i++) m_buffer[i] = v;
		}
	
};

